package com.github.baichuan.web.reactive;

import com.github.baichuan.web.security.JwtCodec;
import com.github.baichuan.web.utils.BearerToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Optional;

@Slf4j
public class JwtSecurityContextRepository implements ServerSecurityContextRepository {
    private JwtCodec<?> codec;

    public JwtSecurityContextRepository(JwtCodec<?> codec){
        this.codec = codec;
    }

    @Override
    public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
        return Mono.empty();
    }

    @Override
    public Mono<SecurityContext> load(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        Optional<String> optional = BearerToken.get(request);
        if(optional.isPresent()){
            try{
                Object principal = codec.decode(optional.get());
                UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(principal, null, null);
                return Mono.just(new SecurityContextImpl(authToken));
            } catch (RuntimeException ex){
                log.error("请求 {} jwt token 解析失败:{}", request.getURI().toString(), ex.getMessage());
                return Mono.empty();
            }
        }
        else{
            log.debug("Authorization bearer is miss");
            return Mono.empty();
        }

    }
}
